package com.cgycms.webdeploy.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.cgycms.webdeploy.aop.Auth;
import com.cgycms.webdeploy.aop.Log;
import com.cgycms.webdeploy.auth.MenuEnum;
import com.cgycms.webdeploy.auth.RolesEnum;
import com.cgycms.webdeploy.common.DownUtil;
import com.cgycms.webdeploy.common.Result;
import com.cgycms.webdeploy.filter.FileTypeFilter;
import com.cgycms.webdeploy.ftp.FtpUtil;
import com.cgycms.webdeploy.storage.DeployConfig;
import com.cgycms.webdeploy.storage.ServersPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @ClassName : DeployController
 * @Description : web上传控制器
 * @Author : 王力超
 * @Date: 2020-11-04 16:36
 */
@RestController
@RequestMapping("/deploy")
public class DeployController {


    @Autowired
    private DeployConfig deployConfig;

    @Autowired
    private FileTypeFilter fileTypeFilter;

    /**
     * 上传服务器文件
     *
     * @param file       文件
     * @param env        环境
     * @param serverPath 上传路径
     * @return
     */
    @Auth(value = "上传文件", menus = {MenuEnum.UPLOAD}, roles = {RolesEnum.ADMIN, RolesEnum.FILE_ADMIN, RolesEnum.DEPLOY_ADMIN})
    @PostMapping("/uploadFile")
    @Log(value = "上传文件操作", type = 2)
    public String uploadByGroup(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "env", required = false) String env,
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "serverPath", required = false) String serverPath) {

        if (StrUtil.isBlank(file.getOriginalFilename())) {
            return Result.fail("上传失败，请选择文件!");
        }

        if (StrUtil.isBlank(serverPath)) {
            return Result.fail("请输入服务器路径！");
        }

        List<FtpUtil> servers = ServersPool.getServersWheres(null, env, title, true);
        if (CollectionUtil.isEmpty(servers)) {
            return Result.fail("无服务器信息,请检查配置服务器信息！");
        }

        try {
            String msg = upload(file.getInputStream(), file.getOriginalFilename(), serverPath, servers);
            if (!StringUtils.isEmpty(msg) && msg.length() > 0) {
                return Result.fail(msg);
            }
            return Result.ok(servers.size());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.fail();
    }


    /**
     * 上传方法
     *
     * @param file       文件
     * @param fileName   文件名称
     * @param serverPath 上传路径
     * @param servers    服务器信息
     * @return
     */
    private String upload(InputStream file, String fileName, String serverPath, List<FtpUtil> servers) {
        StringBuffer msg = new StringBuffer();
        if (true == deployConfig.isDeployDel()) {
            return msg.append("禁止上传,请联系管理员！").toString();
        }
        String name = fileName.substring(fileName.lastIndexOf("\\") + 1);
        if (!fileTypeFilter.valid(file)) {
            return msg.append("不允许上传的文件类型!").toString();
        }
        servers.stream()
                .forEach(server -> {
                    if (!server.upload(file, name, deployConfig.getRetry(), serverPath)) {
                        msg.append("[").append(server.getGroup());
                        msg.append("\n \t").append(server.getHost());
                        msg.append("上传失败!]");
                    }
                    ;
                });
        return msg.toString();
    }


    /**
     * 获取环境信息
     *
     * @return
     */
    @Auth("环境信息")
    @RequestMapping("/getServerEnv")
    public String getServerEnv() {
        Map<String, Object> map = new HashMap<>(2);
        map.put("serverGroup", ServersPool.getServerGroup());
        map.put("serverTitle", ServersPool.getServerAllTitle());
        return Result.ok(map);
    }


    /**
     * 获取服务文件列表
     *
     * @param env        环境
     * @param serverPath 路径
     * @return
     */
    @Auth(value = "文件列表", roles = {RolesEnum.FILE_ADMIN}, menus = {MenuEnum.VIEW})
    @RequestMapping("/getFiles")
    @Log(value = "文件列表操作", type = 2)
    @ResponseBody
    public String getFiles(
            @RequestParam(value = "env", required = false) String env,
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "serverPath", required = false) String serverPath) {

        if (StrUtil.isBlank(serverPath)) {
            return Result.fail("请输入服务器路径！");
        }

        List<FtpUtil> servers = ServersPool.getServersWheres(null, env, title, true);

        if (CollectionUtil.isEmpty(servers)) {
            return Result.fail("无服务器信息,请检查配置服务器信息！");
        }
        List<Map<String, Object>> resultData = new ArrayList<>();

        //处理文件路径
        String filePath = serverPath;
        if (!serverPath.endsWith("/")) {
            filePath += "/";
        }
        String finalFilePath = filePath;
        //并行获取文件信息
        servers.parallelStream().forEach(server -> {
            List<String> list = server.listFilesToList(serverPath);
            for (String s : list) {
                Map<String, Object> file = new HashMap<>(5);
                file.put("path", finalFilePath + s);
                file.put("group", server.getGroup());
                file.put("title", server.getTitle());
                file.put("host", server.getHost());
                file.put("file", s);
                resultData.add(file);
            }
        });
        Collections.reverse(resultData);
        return Result.ok(resultData);
    }

    @Log(value = "文件管理-删除文件操作", type = 2)
    @Auth(value = "批量删除文件", menus = {MenuEnum.DELETE}, roles = {RolesEnum.FILE_ADMIN})
    @RequestMapping("/delFiles")
    @ResponseBody
    public String getFiles(
            @RequestParam List<String> files,
            @RequestParam(value = "host", required = false) String host,
            @RequestParam(value = "env", required = false) String env,
            @RequestParam(value = "title", required = false) String title
    ) {
        if (true == deployConfig.isDeployDel()) {
            return Result.fail("禁止删除操作,请联系管理员！");
        }

        if (CollectionUtil.isEmpty(files)) {
            return Result.fail("请选择要删除的文件！");
        }

        List<FtpUtil> servers = ServersPool.getServersWheres(host, env, title, false);
        if (CollectionUtil.isEmpty(servers)) {
            return Result.fail("无服务器信息,请选择服务信息！");
        }

        List<String> errorList = new ArrayList<>();
        for (String filePath : files) {
            //路径文件名分割
            String name = FileUtil.getName(filePath);
            if (StrUtil.isBlank(name)) {
                errorList.add(filePath);
                continue;
            }
            String path = filePath.substring(0, filePath.lastIndexOf("/") + 1);
            servers.parallelStream().forEach(server -> {
                if (!server.delete(path, name)) {
                    errorList.add(filePath);
                }
            });
        }
        if (errorList.size() > 0) {
            return Result.fail(errorList, "删除失败！");
        }
        return Result.ok();
    }


    @Log(value = "文件管理-下载操作", type = 2)
    @Auth(value = "下载文件", menus = {MenuEnum.DOWNLOAD}, roles = {RolesEnum.FILE_ADMIN})
    @RequestMapping("/getFile")
    @ResponseBody
    public void getFile(
            @RequestParam(value = "path", required = false) String filePath,
            @RequestParam(value = "host", required = false) String host,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        if (true == deployConfig.isDeployDown()) {
            DownUtil.responseError(response, "禁止下载,请联系管理员!");
            return;
        }

        if (StrUtil.isBlank(filePath)) {
            DownUtil.responseError(response, "请选择要下载的文件!");
            return;
        }
        List<FtpUtil> servers = ServersPool.getServersWheres(host, null, null, false);
        if (CollectionUtil.isEmpty(servers)) {
            DownUtil.responseError(response, "无服务器信息,请选择服务信息!");
            return;
        }
        //处理路径
        String path = filePath.substring(0, filePath.lastIndexOf("/") + 1);
        String name = FileUtil.getName(filePath);
        if (StrUtil.isBlank(name)) {
            DownUtil.responseError(response, "请选择文件下载!");
            return;
        }
        servers.stream().limit(1).forEach(server -> {
            String tmp = DownUtil.mkdir(deployConfig.getDownloadTemp());
            server.download(path, name, tmp);
            DownUtil.download(tmp + name, response);
        });
    }

}
